package games;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Random;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;


/**
 * TODO Is your score included in the average you go against???
 * @author Owner
 *
 */
public class BeautyContest extends Game {
	/**
	 * 
	 */
	private static final long serialVersionUID=1L;
	
	private static final String GAME_NAME="BeautyContest";
	private static final String WINNER="winner";
	private static final String GAME_TYPE="HalfMean";
	private static final String WIN="Win";
	
	public static final Font SELECTED_FONT=new Font(Font.SERIF,Font.ITALIC,80);
	public static final Font FONT=new Font(Font.SERIF,Font.BOLD,60);
	public static final int TENS=0;
	public static final int ONES=1;
	public static final int GO=2;


	int time;
	int [] number=new int[2];
	char [] chars=new char[2];
	int players;
	int payOff;
	int max;
	double factor;
	int selected;
	Vector<Move> otherPlayer=new Vector<Move>();
	NumberPainter painter;
	
	FontMetrics fm;
	FontMetrics sfm;
	
	public BeautyContest(Runner runner,int players,int payOff,int total,double factor) {
		super(runner,GAME_NAME);
		this.players=players;
		this.payOff=payOff;
		this.max=total;
		this.factor=factor;
	}
	
	public BeautyContest(Runner runner) {
		this(runner,4,10,100,.5);
	}
	
	public void init() {
		// Turn off metal's use of bold fonts
		UIManager.put("swing.boldMetal",Boolean.FALSE);
	}

	public void start() {
		initComponents();
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		JFrame f=new JFrame();
		f.setLayout(new BorderLayout());
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		BeautyContest ap=new BeautyContest(new Runner());
		ap.init();
		ap.start();
		f.add("Center",ap);
		f.pack();
		f.setVisible(true);
		f.setSize(600,500);
	}
	
	public void getOtherPlayer() {
		try {
		  //BeautyContestPlayerHalfMean100Win10.data
			File f=new File(DATA_FOLDER+GAME_NAME+PLAYER_NAME+GAME_TYPE+max+WIN+payOff+SUFFIX);
			//System.out.println(f.exists());			
			BufferedReader r=new BufferedReader(new FileReader(f));
			//System.out.println(r.readLine());
			
			String[] tokens;
			String current;
			
			while((current=r.readLine())!=null) {
				tokens=current.split(SEPARATOR);
				otherPlayer.add(new Move(tokens[0],Float.parseFloat(tokens[1])));
			}
			//for(Vector<Move>v:otherPlayer) for(Move m:v) System.out.println(m);
			//System.out.println(otherPlayer);
			
			
		} catch(FileNotFoundException e) {
			System.err.println("Can't find the file.");
			e.printStackTrace();
		} catch(IOException e) {
			System.err.println("Problem reading the file.");
			e.printStackTrace();
		}
	}

	public void getMove(float guess) {
		Random random=new Random();
		Move move;
		float total=0;
		Vector<Move> selected=new Vector<Move>(players);
		Vector<Move> winners=new Vector<Move>();
		
		//find the average
		for(int i=1;i<players;i++) {
			move=otherPlayer.get(random.nextInt(otherPlayer.size()));
			total+=move.guess;
			otherPlayer.remove(move);
			selected.add(move);
		}

		
		total+=guess;

		System.out.println(total);
		selected.add(new Move("me",guess));
		System.out.println("players: "+players+" - factor: "+factor);
		total/=players/factor;
		
		System.out.println(total);
		
		//find the winner(s)
		float closest=max;
		float difference;
		for(Move current:selected) {
			log(current.toString());
			difference=Math.abs(total-current.guess);
			if(difference<closest) {
				closest=difference;
				winners.removeAllElements();
				winners.add(current);
			}
			else if(Math.abs(total-current.guess)==closest)
				winners.add(current);
		}
		
		//print the winners
		for(Move current:winners) log(current.toWinnerString());
		
		System.out.println(otherPlayer);
	}
	
	class Move {
		String id;
		float guess;
		
		public Move(String id,float guess) {
			this.id=id;
			this.guess=guess;
		}
		
		public String toString() {
			return id+SEPARATOR+guess;
		}
		
		public String toWinnerString() {
			return WINNER+SEPARATOR+id+(id.equals("me")?SEPARATOR+payOff:"");
		}
	}	
	
	public void initComponents() {
		setLayout(new BorderLayout());
		getOtherPlayer();
		
		fm=getFontMetrics(FONT);
		sfm=getFontMetrics(SELECTED_FONT);
		
		number[ONES]=0;
		chars[ONES]=Integer.toString(number[ONES]).charAt(0);
		number[TENS]=0;
		chars[TENS]=Integer.toString(number[ONES]).charAt(0);
		selected=TENS;

		main=new JPanel(new BorderLayout());
		painter=new NumberPainter();
		
		main.add(BorderLayout.CENTER,painter);
		add(BorderLayout.CENTER,main);

		clock=new Timing();
		getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("S"),"selector");
		getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("G"),"changer");
		
		getActionMap().put("selector",new AbstractAction() {
			/**
			 * 
			 */
			private static final long serialVersionUID=1L;

			public void actionPerformed(ActionEvent e) {
				//System.err.println("Selector pushed");
				selected=(selected+1)%3;
				repaint();
			}
		});		
		getActionMap().put("changer",new AbstractAction() {
			/**
			 * 
			 */
			private static final long serialVersionUID=1L;

			public void actionPerformed(ActionEvent e) {
				//System.err.println("Changer pushed");
				if(selected==GO) {
	      	suspend();
	      	time=clock.getElapsedTime();
					getMove(number[TENS]*10+number[ONES]);
					finished(GAME_NAME,time);
				}
				else {
					number[selected]=(number[selected]+1)%10;
					chars[selected]=Integer.toString(number[selected]).charAt(0);
					//System.err.println(number[selected]);
					repaint();
				}
			}
		});
		
    proceed();
	}
	
	class NumberPainter extends Component {
		/**
		 * 
		 */
		private static final long serialVersionUID=1L;
		BufferedImage img = null;
		
	  public Dimension getPreferredSize(){
	    return new Dimension(600,200);
		}
	  
	  public void paint(Graphics g) {
	    //Dimension size = getSize();
	    int cWidth=getWidth();
	    
	    //draw the tens digit
	    int width=(selected==TENS?sfm.charWidth(chars[TENS]):fm.charWidth(chars[TENS]));
	    g.setFont(selected==TENS?SELECTED_FONT:FONT);
	    g.setColor(selected==TENS?Color.RED:Color.BLACK);
	    g.drawChars(chars,TENS,1,cWidth/2-width-5,250);
	    
	    //draw the ones digit
	    g.setFont(selected==ONES?SELECTED_FONT:FONT);
	    g.setColor(selected==ONES?Color.RED:Color.BLACK);
	    g.drawChars(chars,ONES,1,cWidth/2+5,250);
	    
	    //draw the continue image
			img=loadImage(selected==GO?"selectedGo":"go");
      g.drawImage(img,400,300,null);
		}
	}
}